
/**
 * Copyright 2006 Tim Down.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
if (!Array.prototype.push) {
    Array.prototype.push = function () {
        for (var i = 0; i < arguments.length; i++) {
            this[this.length] = arguments[i];
        }
        return this.length;
    };
}
if (!Array.prototype.shift) {
    Array.prototype.shift = function () {
        if (this.length > 0) {
            var firstItem = this[0];
            for (var i = 0; i < this.length - 1; i++) {
                this[i] = this[i + 1];
            }
            this.length = this.length - 1;
            return firstItem;
        }
    };
}
if (!Array.prototype.splice) {
    Array.prototype.splice = function (startIndex, deleteCount) {
        var itemsAfterDeleted = this.slice(startIndex + deleteCount);
        var itemsDeleted = this.slice(startIndex, startIndex + deleteCount);
        this.length = startIndex;
        var argumentsArray = [];
        for (var i = 0; i < arguments.length; i++) {
            argumentsArray[i] = arguments[i];
        }
        var itemsToAppend = (argumentsArray.length > 2) ? itemsAfterDeleted = argumentsArray.slice(2).concat(itemsAfterDeleted) : itemsAfterDeleted;
        for (i = 0; i < itemsToAppend.length; i++) {
            this.push(itemsToAppend[i]);
        }
        return itemsDeleted;
    };
}
var log4javascript;
var SimpleDateFormat;
(function () {
    function isUndefined(obj) {
        return typeof obj == "undefined";
    }
    (function () {
        var regex = /('[^']*')|(G+|y+|M+|w+|W+|D+|d+|F+|E+|a+|H+|k+|K+|h+|m+|s+|S+|Z+)|([a-zA-Z]+)|([^a-zA-Z']+)/;
        var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
        var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
        var TEXT2 = 0, TEXT3 = 1, NUMBER = 2, YEAR = 3, MONTH = 4, TIMEZONE = 5;
        var types = {G:TEXT2, y:YEAR, Y:YEAR, M:MONTH, w:NUMBER, W:NUMBER, D:NUMBER, d:NUMBER, F:NUMBER, E:TEXT3, a:TEXT2, H:NUMBER, k:NUMBER, K:NUMBER, h:NUMBER, m:NUMBER, s:NUMBER, S:NUMBER, Z:TIMEZONE};
        var ONE_DAY = 24 * 60 * 60 * 1000;
        var ONE_WEEK = 7 * ONE_DAY;
        var DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK = 1;
        Date.prototype.getDifference = function (date) {
            return this.getTime() - date.getTime();
        };
        Date.prototype.isBefore = function (d) {
            return this.getTime() < d.getTime();
        };
        Date.prototype.getWeekInYear = function (minimalDaysInFirstWeek) {
            if (isUndefined(this.minimalDaysInFirstWeek)) {
                minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK;
            }
            var previousSunday = new Date(this.getTime() - this.getDay() * ONE_DAY);
            previousSunday = new Date(previousSunday.getFullYear(), previousSunday.getMonth(), previousSunday.getDate());
            var startOfYear = new Date(this.getFullYear(), 0, 1);
            var numberOfSundays = previousSunday.isBefore(startOfYear) ? 0 : 1 + Math.floor((previousSunday.getTime() - startOfYear.getTime()) / ONE_WEEK);
            var numberOfDaysInFirstWeek = 7 - startOfYear.getDay();
            var weekInYear = numberOfSundays;
            if (numberOfDaysInFirstWeek >= minimalDaysInFirstWeek) {
                weekInYear++;
            }
            return weekInYear;
        };
        Date.prototype.getWeekInMonth = function (minimalDaysInFirstWeek) {
            if (isUndefined(this.minimalDaysInFirstWeek)) {
                minimalDaysInFirstWeek = DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK;
            }
            var previousSunday = new Date(this.getTime() - this.getDay() * ONE_DAY);
            previousSunday = new Date(previousSunday.getFullYear(), previousSunday.getMonth(), previousSunday.getDate());
            var startOfMonth = new Date(this.getFullYear(), this.getMonth(), 1);
            var numberOfSundays = previousSunday.isBefore(startOfMonth) ? 0 : 1 + Math.floor((previousSunday.getTime() - startOfMonth.getTime()) / ONE_WEEK);
            var numberOfDaysInFirstWeek = 7 - startOfMonth.getDay();
            var weekInMonth = numberOfSundays;
            if (numberOfDaysInFirstWeek >= minimalDaysInFirstWeek) {
                weekInMonth++;
            }
            return weekInMonth;
        };
        Date.prototype.getDayInYear = function () {
            var startOfYear = new Date(this.getFullYear(), 0, 1);
            return 1 + Math.floor((this.getTime() - startOfYear.getTime()) / ONE_DAY);
        };
        SimpleDateFormat = function (formatString) {
            this.formatString = formatString;
        };
        SimpleDateFormat.prototype.setMinimalDaysInFirstWeek = function (days) {
            this.minimalDaysInFirstWeek = days;
        };
        SimpleDateFormat.prototype.getMinimalDaysInFirstWeek = function (days) {
            return isUndefined(this.minimalDaysInFirstWeek) ? DEFAULT_MINIMAL_DAYS_IN_FIRST_WEEK : this.minimalDaysInFirstWeek;
        };
        SimpleDateFormat.prototype.format = function (date) {
            var formattedString = "";
            var result;
            var padWithZeroes = function (str, len) {
                while (str.length < len) {
                    str = "0" + str;
                }
                return str;
            };
            var formatText = function (data, numberOfLetters, minLength) {
                return (numberOfLetters >= 4) ? data : data.substr(0, Math.max(minLength, numberOfLetters));
            };
            var formatNumber = function (data, numberOfLetters) {
                var dataString = "" + data;
                return padWithZeroes(dataString, numberOfLetters);
            };
            var searchString = this.formatString;
            while ((result = regex.exec(searchString))) {
                var matchedString = result[0];
                var quotedString = result[1];
                var patternLetters = result[2];
                var otherLetters = result[3];
                var otherCharacters = result[4];
                if (quotedString) {
                    if (quotedString == "''") {
                        formattedString += "'";
                    } else {
                        formattedString += quotedString.substring(1, quotedString.length - 1);
                    }
                } else {
                    if (otherLetters) {
                    } else {
                        if (otherCharacters) {
                            formattedString += otherCharacters;
                        } else {
                            if (patternLetters) {
                                var patternLetter = patternLetters.charAt(0);
                                var numberOfLetters = patternLetters.length;
                                var rawData = "";
                                switch (patternLetter) {
                                  case "G":
                                    rawData = "AD";
                                    break;
                                  case "y":
                                    rawData = date.getFullYear();
                                    break;
                                  case "M":
                                    rawData = date.getMonth();
                                    break;
                                  case "w":
                                    rawData = date.getWeekInYear(this.getMinimalDaysInFirstWeek());
                                    break;
                                  case "W":
                                    rawData = date.getWeekInMonth(this.getMinimalDaysInFirstWeek());
                                    break;
                                  case "D":
                                    rawData = date.getDayInYear();
                                    break;
                                  case "d":
                                    rawData = date.getDate();
                                    break;
                                  case "F":
                                    rawData = 1 + Math.floor((date.getDate() - 1) / 7);
                                    break;
                                  case "E":
                                    rawData = dayNames[date.getDay()];
                                    break;
                                  case "a":
                                    rawData = (date.getHours() >= 12) ? "PM" : "AM";
                                    break;
                                  case "H":
                                    rawData = date.getHours();
                                    break;
                                  case "k":
                                    rawData = 1 + date.getHours();
                                    break;
                                  case "K":
                                    rawData = date.getHours() % 12;
                                    break;
                                  case "h":
                                    rawData = 1 + (date.getHours() % 12);
                                    break;
                                  case "m":
                                    rawData = date.getMinutes();
                                    break;
                                  case "s":
                                    rawData = date.getSeconds();
                                    break;
                                  case "S":
                                    rawData = date.getMilliseconds();
                                    break;
                                  case "Z":
                                    rawData = date.getTimezoneOffset();
                                    break;
                                }
                                switch (types[patternLetter]) {
                                  case TEXT2:
                                    formattedString += formatText(rawData, numberOfLetters, 2);
                                    break;
                                  case TEXT3:
                                    formattedString += formatText(rawData, numberOfLetters, 3);
                                    break;
                                  case NUMBER:
                                    formattedString += formatNumber(rawData, numberOfLetters);
                                    break;
                                  case YEAR:
                                    if (numberOfLetters <= 2) {
                                        var dataString = "" + rawData;
                                        formattedString += dataString.substr(2, 2);
                                    } else {
                                        formattedString += formatNumber(rawData, numberOfLetters);
                                    }
                                    break;
                                  case MONTH:
                                    if (numberOfLetters >= 3) {
                                        formattedString += formatText(monthNames[rawData], numberOfLetters, numberOfLetters);
                                    } else {
                                        formattedString += formatNumber(rawData + 1, numberOfLetters);
                                    }
                                    break;
                                  case TIMEZONE:
                                    var isPositive = (rawData > 0);
                                    var prefix = isPositive ? "-" : "+";
                                    var absData = Math.abs(rawData);
                                    var hours = "" + Math.floor(absData / 60);
                                    hours = padWithZeroes(hours, 2);
                                    var minutes = "" + (absData % 60);
                                    minutes = padWithZeroes(minutes, 2);
                                    formattedString += prefix + hours + minutes;
                                    break;
                                }
                            }
                        }
                    }
                }
                searchString = searchString.substr(result.index + result[0].length);
            }
            return formattedString;
        };
    })();
    var applicationStartDate = new Date();
    var uniqueId = "log4javascript_" + applicationStartDate.getTime() + "_" + Math.floor(Math.random() * 100000000);
    var emptyFunction = function () {
    };
    var newLine = "\r\n";
    log4javascript = {};
    log4javascript.version = "1.3.1";
    function getExceptionStringRep(ex) {
        if (ex) {
            var exStr = "Exception: ";
            if (ex.message) {
                exStr += ex.message;
            } else {
                if (ex.description) {
                    exStr += ex.description;
                }
            }
            if (ex.lineNumber) {
                exStr += " on line number " + ex.lineNumber;
            }
            if (ex.fileName) {
                exStr += " in file " + ex.fileName;
            }
            if (showStackTraces && ex.stack) {
                exStr += newLine + "Stack trace:" + newLine + ex.stack;
            }
            return exStr;
        }
        return null;
    }
    function formatObjectExpansion(obj, depth, indentation) {
        var i, output, childDepth, childIndentation, childLines;
        if ((obj instanceof Array) && depth > 0) {
            if (!indentation) {
                indentation = "";
            }
            output = "[" + newLine;
            childDepth = depth - 1;
            childIndentation = indentation + "  ";
            childLines = [];
            for (i = 0; i < obj.length; i++) {
                childLines.push(childIndentation + formatObjectExpansion(obj[i], childDepth, childIndentation));
            }
            output += childLines.join("," + newLine) + newLine + indentation + "]";
            return output;
        } else {
            if (typeof obj == "object" && depth > 0) {
                if (!indentation) {
                    indentation = "";
                }
                output = "" + "{" + newLine;
                childDepth = depth - 1;
                childIndentation = indentation + "  ";
                childLines = [];
                for (i in obj) {
                    childLines.push(childIndentation + i + ": " + formatObjectExpansion(obj[i], childDepth, childIndentation));
                }
                output += childLines.join("," + newLine) + newLine + indentation + "}";
                return output;
            } else {
                if (typeof obj == "string") {
                    return obj;
                } else {
                    return obj.toString();
                }
            }
        }
    }
    function escapeNewLines(str) {
        return str.replace(/\r\n|\r|\n/g, "\\r\\n");
    }
    function urlEncode(str) {
        return escape(str).replace(/\+/g, "%2B").replace(/"/g, "%22").replace(/'/g, "%27").replace(/\//g, "%2F");
    }
    function bool(obj) {
        return Boolean(obj);
    }
    function array_remove(arr, val) {
        var index = -1;
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] === val) {
                index = i;
                break;
            }
        }
        if (index >= 0) {
            arr.splice(index, 1);
            return true;
        } else {
            return false;
        }
    }
    function extractBooleanFromParam(param, defaultValue) {
        if (isUndefined(param)) {
            return defaultValue;
        } else {
            return bool(param);
        }
    }
    function extractStringFromParam(param, defaultValue) {
        if (isUndefined(param)) {
            return defaultValue;
        } else {
            return String(param);
        }
    }
    function extractIntFromParam(param, defaultValue) {
        if (isUndefined(param)) {
            return defaultValue;
        } else {
            try {
                var value = parseInt(param, 10);
                return isNaN(value) ? defaultValue : value;
            }
            catch (ex) {
                logLog.warn("Invalid int param " + param, ex);
                return defaultValue;
            }
        }
    }
    function extractFunctionFromParam(param, defaultValue) {
        if (typeof param == "function") {
            return param;
        } else {
            return defaultValue;
        }
    }
    var logLog = {quietMode:false, setQuietMode:function (quietMode) {
        this.quietMode = bool(quietMode);
    }, numberOfErrors:0, alertAllErrors:false, setAlertAllErrors:function (alertAllErrors) {
        this.alertAllErrors = alertAllErrors;
    }, debug:function (message, exception) {
    }, warn:function (message, exception) {
    }, error:function (message, exception) {
        if (++this.numberOfErrors == 1 || this.alertAllErrors) {
            if (!this.quietMode) {
                var alertMessage = "log4javascript error: " + message;
                if (exception) {
                    alertMessage += newLine + newLine + "Original error: " + getExceptionStringRep(exception);
                }
                alert(alertMessage);
            }
        }
    }};
    log4javascript.logLog = logLog;
    var errorListeners = [];
    log4javascript.addErrorListener = function (listener) {
        if (typeof listener == "function") {
            errorListeners.push(listener);
        } else {
            handleError("addErrorListener: listener supplied was not a function");
        }
    };
    log4javascript.removeErrorListener = function (listener) {
        array_remove(errorListeners, listener);
    };
    function handleError(message, exception) {
        logLog.error(message, exception);
        for (var i = 0; i < errorListeners.length; i++) {
            errorListeners[i](message, exception);
        }
    }
    var enabled = (typeof log4javascript_disabled != "undefined") && log4javascript_disabled ? false : true;
    log4javascript.setEnabled = function (enable) {
        enabled = bool(enable);
    };
    log4javascript.isEnabled = function () {
        return enabled;
    };
    log4javascript.evalInScope = function (expr) {
        return eval(expr);
    };
    var showStackTraces = false;
    log4javascript.setShowStackTraces = function (show) {
        showStackTraces = bool(show);
    };
    function Logger(name) {
        this.name = name;
        var appenders = [];
        var loggerLevel = Level.DEBUG;
        this.addAppender = function (appender) {
            if (appender instanceof log4javascript.Appender) {
                appenders.push(appender);
            } else {
                handleError("Logger.addAppender: appender supplied is not a subclass of Appender");
            }
        };
        this.removeAppender = function (appender) {
            array_remove(appenders, appender);
        };
        this.removeAllAppenders = function (appender) {
            appenders.length = 0;
        };
        this.log = function (level, message, exception) {
            if (level.isGreaterOrEqual(loggerLevel)) {
                var loggingEvent = new LoggingEvent(this, new Date(), level, message, exception);
                for (var i = 0; i < appenders.length; i++) {
                    appenders[i].doAppend(loggingEvent);
                }
            }
        };
        this.setLevel = function (level) {
            loggerLevel = level;
        };
        this.getLevel = function () {
            return loggerLevel;
        };
    }
    Logger.prototype = {trace:function (message, exception) {
        this.log(Level.TRACE, message, exception);
    }, debug:function (message, exception) {
        this.log(Level.DEBUG, message, exception);
    }, info:function (message, exception) {
        this.log(Level.INFO, message, exception);
    }, warn:function (message, exception) {
        this.log(Level.WARN, message, exception);
    }, error:function (message, exception) {
        this.log(Level.ERROR, message, exception);
    }, fatal:function (message, exception) {
        this.log(Level.FATAL, message, exception);
    }};
    Logger.prototype.trace.isEntryPoint = true;
    Logger.prototype.debug.isEntryPoint = true;
    Logger.prototype.info.isEntryPoint = true;
    Logger.prototype.warn.isEntryPoint = true;
    Logger.prototype.error.isEntryPoint = true;
    Logger.prototype.fatal.isEntryPoint = true;
    var loggers = {};
    log4javascript.getLogger = function (loggerName) {
        if (!(typeof loggerName == "string")) {
            loggerName = "[anonymous]";
        }
        if (!loggers[loggerName]) {
            loggers[loggerName] = new Logger(loggerName);
        }
        return loggers[loggerName];
    };
    var defaultLogger = null;
    log4javascript.getDefaultLogger = function () {
        if (!defaultLogger) {
            defaultLogger = log4javascript.getLogger("[default]");
            var a = new log4javascript.PopUpAppender();
            defaultLogger.addAppender(a);
        }
        return defaultLogger;
    };
    var nullLogger = null;
    log4javascript.getNullLogger = function () {
        if (!nullLogger) {
            nullLogger = log4javascript.getLogger("[null]");
        }
        return nullLogger;
    };
    var Level = function (level, name) {
        this.level = level;
        this.name = name;
    };
    Level.prototype = {toString:function () {
        return this.name;
    }, equals:function (level) {
        return this.level == level.level;
    }, isGreaterOrEqual:function (level) {
        return this.level >= level.level;
    }};
    Level.ALL = new Level(Number.MIN_VALUE, "ALL");
    Level.TRACE = new Level(10000, "TRACE");
    Level.DEBUG = new Level(20000, "DEBUG");
    Level.INFO = new Level(30000, "INFO");
    Level.WARN = new Level(40000, "WARN");
    Level.ERROR = new Level(50000, "ERROR");
    Level.FATAL = new Level(60000, "FATAL");
    Level.OFF = new Level(Number.MAX_VALUE, "OFF");
    log4javascript.Level = Level;
    var LoggingEvent = function (logger, timeStamp, level, message, exception) {
        this.logger = logger;
        this.timeStamp = timeStamp;
        this.timeStampInSeconds = Math.floor(timeStamp.getTime() / 1000);
        this.level = level;
        this.message = message;
        this.exception = exception;
    };
    LoggingEvent.prototype.getThrowableStrRep = function () {
        return this.exception ? getExceptionStringRep(this.exception) : "";
    };
    log4javascript.LoggingEvent = LoggingEvent;
    var Layout = function () {
    };
    Layout.prototype = {defaults:{loggerKey:"logger", timeStampKey:"timestamp", levelKey:"level", messageKey:"message", exceptionKey:"exception", urlKey:"url"}, loggerKey:"logger", timeStampKey:"timestamp", levelKey:"level", messageKey:"message", exceptionKey:"exception", urlKey:"url", batchHeader:"", batchFooter:"", batchSeparator:"", format:function (loggingEvent) {
        handleError("Layout.format: layout supplied has no format() method");
    }, ignoresThrowable:function () {
        handleError("Layout.ignoresThrowable: layout supplied has no ignoresThrowable() method");
    }, getContentType:function () {
        return "text/plain";
    }, allowBatching:function () {
        return true;
    }, getDataValues:function (loggingEvent) {
        var dataValues = [[this.loggerKey, loggingEvent.logger.name], [this.timeStampKey, loggingEvent.timeStampInSeconds], [this.levelKey, loggingEvent.level.name], [this.urlKey, window.location.href], [this.messageKey, loggingEvent.message]];
        if (loggingEvent.exception) {
            dataValues.push([this.exceptionKey, getExceptionStringRep(loggingEvent.exception)]);
        }
        if (this.hasCustomFields()) {
            for (var i = 0; i < this.customFields.length; i++) {
                dataValues.push([this.customFields[i].name, this.customFields[i].value]);
            }
        }
        return dataValues;
    }, setKeys:function (loggerKey, timeStampKey, levelKey, messageKey, exceptionKey, urlKey) {
        this.loggerKey = extractStringFromParam(loggerKey, this.defaults.loggerKey);
        this.timeStampKey = extractStringFromParam(timeStampKey, this.defaults.timeStampKey);
        this.levelKey = extractStringFromParam(levelKey, this.defaults.levelKey);
        this.messageKey = extractStringFromParam(messageKey, this.defaults.messageKey);
        this.exceptionKey = extractStringFromParam(exceptionKey, this.defaults.exceptionKey);
        this.urlKey = extractStringFromParam(urlKey, this.defaults.urlKey);
    }, setCustomField:function (name, value) {
        var fieldUpdated = false;
        for (var i = 0; i < this.customFields.length; i++) {
            if (this.customFields[i].name === name) {
                this.customFields[i].value = value;
                fieldUpdated = true;
            }
        }
        if (!fieldUpdated) {
            this.customFields.push({"name":name, "value":value});
        }
    }, hasCustomFields:function () {
        return (this.customFields.length > 0);
    }};
    log4javascript.Layout = Layout;
    var SimpleLayout = function () {
        this.customFields = [];
    };
    SimpleLayout.prototype = new Layout();
    SimpleLayout.prototype.format = function (loggingEvent) {
        return loggingEvent.level.name + " - " + loggingEvent.message;
    };
    SimpleLayout.prototype.ignoresThrowable = function (loggingEvent) {
        return true;
    };
    log4javascript.SimpleLayout = SimpleLayout;
    var NullLayout = function () {
        this.customFields = [];
    };
    NullLayout.prototype = new Layout();
    NullLayout.prototype.format = function (loggingEvent) {
        return loggingEvent.message;
    };
    NullLayout.prototype.ignoresThrowable = function (loggingEvent) {
        return true;
    };
    log4javascript.NullLayout = NullLayout;
    var XmlLayout = function () {
        this.customFields = [];
    };
    XmlLayout.prototype = new Layout();
    XmlLayout.prototype.getContentType = function () {
        return "text/xml";
    };
    XmlLayout.prototype.escapeCdata = function (str) {
        return str.replace(/\]\]>/, "]]>]]&gt;<![CDATA[");
    };
    XmlLayout.prototype.format = function (loggingEvent) {
        var str = "<log4javascript:event logger=\"" + loggingEvent.logger.name + "\" timestamp=\"" + loggingEvent.timeStampInSeconds + "\" level=\"" + loggingEvent.level.name + "\">" + newLine + "<log4javascript:message><![CDATA[" + this.escapeCdata(loggingEvent.message.toString()) + "]]></log4javascript:message>" + newLine;
        if (this.hasCustomFields()) {
            for (var i = 0; i < this.customFields.length; i++) {
                str += "<log4javascript:customfield name=\"" + this.customFields[i].name + "\"><![CDATA[" + this.customFields[i].value.toString() + "]]></log4javascript:customfield>" + newLine;
            }
        }
        if (loggingEvent.exception) {
            str += "<log4javascript:exception><![CDATA[" + getExceptionStringRep(loggingEvent.exception) + "]]></log4javascript:exception>" + newLine;
        }
        str += "</log4javascript:event>" + newLine + newLine;
        return str;
    };
    XmlLayout.prototype.ignoresThrowable = function (loggingEvent) {
        return false;
    };
    log4javascript.XmlLayout = XmlLayout;
    var JsonLayout = function (readable, loggerKey, timeStampKey, levelKey, messageKey, exceptionKey, urlKey) {
        this.readable = bool(readable);
        this.batchHeader = this.readable ? "[" + newLine : "[";
        this.batchFooter = this.readable ? "]" + newLine : "]";
        this.batchSeparator = this.readable ? "," + newLine : ",";
        this.setKeys(loggerKey, timeStampKey, levelKey, messageKey, exceptionKey, urlKey);
        this.propertySeparator = this.readable ? ", " : ",";
        this.colon = this.readable ? ": " : ":";
        this.customFields = [];
    };
    JsonLayout.prototype = new Layout();
    JsonLayout.prototype.setReadable = function (readable) {
        this.readable = bool(readable);
    };
    JsonLayout.prototype.isReadable = function () {
        return this.readable;
    };
    JsonLayout.prototype.format = function (loggingEvent) {
        var dataValues = this.getDataValues(loggingEvent);
        var str = "{";
        if (this.readable) {
            str += newLine;
        }
        for (var i = 0; i < dataValues.length; i++) {
            if (this.readable) {
                str += "\t";
            }
            var valType = typeof dataValues[i][1];
            var val = (valType != "number" && valType != "boolean") ? "\"" + escapeNewLines(dataValues[i][1].toString().replace(/\"/g, "\\\"")) + "\"" : dataValues[i][1];
            str += "\"" + dataValues[i][0] + "\"" + this.colon + val;
            if (i < dataValues.length - 1) {
                str += this.propertySeparator;
            }
            if (this.readable) {
                str += newLine;
            }
        }
        str += "}";
        if (this.readable) {
            str += newLine;
        }
        return str;
    };
    JsonLayout.prototype.ignoresThrowable = function (loggingEvent) {
        return false;
    };
    log4javascript.JsonLayout = JsonLayout;
    var HttpPostDataLayout = function (loggerKey, timeStampKey, levelKey, messageKey, exceptionKey, urlKey) {
        this.setKeys(loggerKey, timeStampKey, levelKey, messageKey, exceptionKey, urlKey);
        this.customFields = [];
    };
    HttpPostDataLayout.prototype = new Layout();
    HttpPostDataLayout.prototype.allowBatching = function () {
        return false;
    };
    HttpPostDataLayout.prototype.format = function (loggingEvent) {
        var dataValues = this.getDataValues(loggingEvent);
        var queryBits = [];
        for (var i = 0; i < dataValues.length; i++) {
            queryBits.push(urlEncode(dataValues[i][0]) + "=" + urlEncode(dataValues[i][1]));
        }
        return queryBits.join("&");
    };
    HttpPostDataLayout.prototype.ignoresThrowable = function (loggingEvent) {
        return false;
    };
    log4javascript.HttpPostDataLayout = HttpPostDataLayout;
    var PatternLayout = function (pattern) {
        if (pattern) {
            this.pattern = pattern;
        } else {
            this.pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
        }
        this.customFields = [];
    };
    PatternLayout.TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n";
    PatternLayout.DEFAULT_CONVERSION_PATTERN = "%m%n";
    PatternLayout.ISO8601_DATEFORMAT = "yyyy-MM-dd HH:mm:ss,SSS";
    PatternLayout.DATETIME_DATEFORMAT = "dd MMM yyyy HH:mm:ss,SSS";
    PatternLayout.ABSOLUTETIME_DATEFORMAT = "HH:mm:ss,SSS";
    PatternLayout.prototype = new Layout();
    PatternLayout.prototype.format = function (loggingEvent) {
        var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([cdfmMnpr%])(\{([^\}]+)\})?|([^%]+)/;
        var formattedString = "";
        var result;
        var searchString = this.pattern;
        while ((result = regex.exec(searchString))) {
            var matchedString = result[0];
            var padding = result[1];
            var truncation = result[2];
            var conversionCharacter = result[3];
            var specifier = result[5];
            var text = result[6];
            if (text) {
                formattedString += "" + text;
            } else {
                var replacement = "";
                switch (conversionCharacter) {
                  case "c":
                    var loggerName = loggingEvent.logger.name;
                    if (specifier) {
                        var precision = parseInt(specifier, 10);
                        var loggerNameBits = loggingEvent.logger.name.split(".");
                        if (precision >= loggerNameBits.length) {
                            replacement = loggerName;
                        } else {
                            replacement = loggerNameBits.slice(loggerNameBits.length - precision).join(".");
                        }
                    } else {
                        replacement = loggerName;
                    }
                    break;
                  case "d":
                    var dateFormat = PatternLayout.ISO8601_DATEFORMAT;
                    if (specifier) {
                        dateFormat = specifier;
                        if (dateFormat == "ISO8601") {
                            dateFormat = PatternLayout.ISO8601_DATEFORMAT;
                        } else {
                            if (dateFormat == "ABSOLUTE") {
                                dateFormat = PatternLayout.ABSOLUTETIME_DATEFORMAT;
                            } else {
                                if (dateFormat == "DATE") {
                                    dateFormat = PatternLayout.DATETIME_DATEFORMAT;
                                }
                            }
                        }
                    }
                    replacement = (new SimpleDateFormat(dateFormat)).format(loggingEvent.timeStamp);
                    break;
                  case "f":
                    if (this.hasCustomFields()) {
                        var fieldIndex = 0;
                        if (specifier) {
                            fieldIndex = parseInt(specifier, 10);
                            if (isNaN(fieldIndex)) {
                                handleError("PatternLayout.format: invalid specifier '" + specifier + "' for conversion character 'f' - should be a number");
                            } else {
                                if (fieldIndex === 0) {
                                    handleError("PatternLayout.format: invalid specifier '" + specifier + "' for conversion character 'f' - must be greater than zero");
                                } else {
                                    if (fieldIndex > this.customFields.length) {
                                        handleError("PatternLayout.format: invalid specifier '" + specifier + "' for conversion character 'f' - there aren't that many custom fields");
                                    } else {
                                        fieldIndex = fieldIndex - 1;
                                    }
                                }
                            }
                        }
                        replacement = this.customFields[fieldIndex].value;
                    }
                    break;
                  case "m":
                    if (specifier) {
                        var depth = parseInt(specifier, 10);
                        if (isNaN(depth)) {
                            handleError("PatternLayout.format: invalid specifier '" + specifier + "' for conversion character 'm' - should be a number");
                            replacement = loggingEvent.message;
                        } else {
                            replacement = formatObjectExpansion(loggingEvent.message, depth);
                        }
                    } else {
                        replacement = loggingEvent.message;
                    }
                    break;
                  case "n":
                    replacement = newLine;
                    break;
                  case "p":
                    replacement = loggingEvent.level.name;
                    break;
                  case "r":
                    replacement = "" + loggingEvent.timeStamp.getDifference(applicationStartDate);
                    break;
                  case "%":
                    replacement = "%";
                    break;
                  default:
                    replacement = matchedString;
                    break;
                }
                var len;
                if (truncation) {
                    len = parseInt(truncation.substr(1), 10);
                    var strLen = replacement.length;
                    if (len < strLen) {
                        replacement = replacement.substring(strLen - len, strLen);
                    }
                }
                if (padding) {
                    if (padding.charAt(0) == "-") {
                        len = parseInt(padding.substr(1), 10);
                        while (replacement.length < len) {
                            replacement += " ";
                        }
                    } else {
                        len = parseInt(padding, 10);
                        while (replacement.length < len) {
                            replacement = " " + replacement;
                        }
                    }
                }
                formattedString += replacement;
            }
            searchString = searchString.substr(result.index + result[0].length);
        }
        return formattedString;
    };
    PatternLayout.prototype.ignoresThrowable = function (loggingEvent) {
        return true;
    };
    log4javascript.PatternLayout = PatternLayout;
    var Appender = function () {
    };
    Appender.prototype = {layout:new PatternLayout(), threshold:Level.ALL, doAppend:function (loggingEvent) {
        if (enabled && loggingEvent.level.level >= this.threshold.level) {
            this.append(loggingEvent);
        }
    }, append:function (loggingEvent) {
    }, setLayout:function (layout) {
        if (layout instanceof Layout) {
            this.layout = layout;
        } else {
            handleError("Appender.setLayout: layout supplied to " + this.toString() + " is not a subclass of Layout");
        }
    }, getLayout:function () {
        return this.layout;
    }, setThreshold:function (threshold) {
        if (threshold instanceof Level) {
            this.threshold = threshold;
        } else {
            handleError("Appender.setThreshold: threshold supplied to " + this.toString() + " is not a subclass of Level");
        }
    }, getThreshold:function () {
        return this.threshold;
    }, toString:function () {
        return "[Base Appender]";
    }};
    log4javascript.Appender = Appender;
    var AlertAppender = function (layout) {
        if (layout) {
            this.setLayout(layout);
        }
    };
    AlertAppender.prototype = new Appender();
    AlertAppender.prototype.layout = new SimpleLayout();
    AlertAppender.prototype.append = function (loggingEvent) {
        var formattedMessage = this.getLayout().format(loggingEvent);
        if (this.getLayout().ignoresThrowable()) {
            formattedMessage += loggingEvent.getThrowableStrRep();
        }
        alert(formattedMessage);
    };
    AlertAppender.prototype.toString = function () {
        return "[AlertAppender]";
    };
    log4javascript.AlertAppender = AlertAppender;
    var AjaxAppender = function (url, layout, timed, waitForResponse, batchSize, timerInterval, requestSuccessCallback, failCallback) {
        var appender = this;
        var isSupported = true;
        if (!url) {
            handleError("AjaxAppender: URL must be specified in constructor");
            isSupported = false;
        }
        timed = extractBooleanFromParam(timed, this.defaults.timed);
        waitForResponse = extractBooleanFromParam(waitForResponse, this.defaults.waitForResponse);
        batchSize = extractIntFromParam(batchSize, this.defaults.batchSize);
        timerInterval = extractIntFromParam(timerInterval, this.defaults.timerInterval);
        requestSuccessCallback = extractFunctionFromParam(requestSuccessCallback, this.defaults.requestSuccessCallback);
        failCallback = extractFunctionFromParam(failCallback, this.defaults.failCallback);
        var sessionId = null;
        var queuedLoggingEvents = [];
        var queuedRequests = [];
        var sending = false;
        var initialized = false;
        function checkCanConfigure(configOptionName) {
            if (initialized) {
                handleError("AjaxAppender: configuration option '" + configOptionName + "' may not be set after the appender has been initialized");
                return false;
            }
            return true;
        }
        this.getSessionId = function () {
            return sessionId;
        };
        this.setSessionId = function (sessionIdParam) {
            sessionId = extractStringFromParam(sessionIdParam, null);
            this.layout.setCustomField("sessionid", sessionId);
        };
        this.setLayout = function (layout) {
            if (checkCanConfigure("layout")) {
                this.layout = layout;
                if (sessionId !== null) {
                    this.setSessionId(sessionId);
                }
            }
        };
        if (layout) {
            this.setLayout(layout);
        }
        this.isTimed = function () {
            return timed;
        };
        this.setTimed = function (timedParam) {
            if (checkCanConfigure("timed")) {
                timed = bool(timedParam);
            }
        };
        this.getTimerInterval = function () {
            return timerInterval;
        };
        this.setTimerInterval = function (timerIntervalParam) {
            if (checkCanConfigure("timerInterval")) {
                timerInterval = extractIntFromParam(timerIntervalParam, timerInterval);
            }
        };
        this.isWaitForResponse = function () {
            return waitForResponse;
        };
        this.setWaitForResponse = function (waitForResponseParam) {
            if (checkCanConfigure("waitForResponse")) {
                waitForResponse = bool(waitForResponseParam);
            }
        };
        this.getBatchSize = function () {
            return batchSize;
        };
        this.setBatchSize = function (batchSizeParam) {
            if (checkCanConfigure("batchSize")) {
                batchSize = extractIntFromParam(batchSizeParam, batchSize);
            }
        };
        this.setRequestSuccessCallback = function (requestSuccessCallbackParam) {
            requestSuccessCallback = extractFunctionFromParam(requestSuccessCallbackParam, requestSuccessCallback);
        };
        this.setFailCallback = function (failCallbackParam) {
            failCallback = extractFunctionFromParam(failCallbackParam, failCallback);
        };
        function sendAll() {
            if (isSupported && enabled) {
                sending = true;
                var currentRequestBatch;
                if (waitForResponse) {
                    if (queuedRequests.length > 0) {
                        currentRequestBatch = queuedRequests.shift();
                        sendRequest(preparePostData(currentRequestBatch), sendAll);
                    } else {
                        sending = false;
                        if (timed) {
                            scheduleSending();
                        }
                    }
                } else {
                    while ((currentRequestBatch = queuedRequests.shift())) {
                        sendRequest(preparePostData(currentRequestBatch));
                    }
                    sending = false;
                    if (timed) {
                        scheduleSending();
                    }
                }
            }
        }
        this.sendAll = sendAll;
        function preparePostData(batchedLoggingEvents) {
            var formattedMessages = [];
            var currentLoggingEvent;
            var postData = "";
            while ((currentLoggingEvent = batchedLoggingEvents.shift())) {
                var currentFormattedMessage = appender.getLayout().format(currentLoggingEvent);
                if (appender.getLayout().ignoresThrowable()) {
                    currentFormattedMessage += loggingEvent.getThrowableStrRep();
                }
                formattedMessages.push(currentFormattedMessage);
            }
            if (batchedLoggingEvents.length == 1) {
                postData = formattedMessages.join("");
            } else {
                postData = appender.getLayout().batchHeader + formattedMessages.join(appender.getLayout().batchSeparator) + appender.getLayout().batchFooter;
            }
            return postData;
        }
        function scheduleSending() {
            setTimeout(sendAll, timerInterval);
        }
        function getXmlHttp() {
            var xmlHttp = null;
            if (typeof XMLHttpRequest == "object" || typeof XMLHttpRequest == "function") {
                xmlHttp = new XMLHttpRequest();
            } else {
                try {
                    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
                }
                catch (e2) {
                    try {
                        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    catch (e3) {
                        var msg = "AjaxAppender: could not create XMLHttpRequest object. AjaxAppender disabled";
                        handleError(msg);
                        isSupported = false;
                        if (failCallback) {
                            failCallback(msg);
                        }
                    }
                }
            }
            return xmlHttp;
        }
        function sendRequest(postData, successCallback) {
            try {
                var xmlHttp = getXmlHttp();
                if (isSupported) {
                    if (xmlHttp.overrideMimeType) {
                        xmlHttp.overrideMimeType(appender.getLayout().getContentType());
                    }
                    xmlHttp.onreadystatechange = function () {
                        if (xmlHttp.readyState == 4) {
                            var success = (isUndefined(xmlHttp.status) || xmlHttp.status === 0 || (xmlHttp.status >= 200 && xmlHttp.status < 300));
                            if (success) {
                                if (requestSuccessCallback) {
                                    requestSuccessCallback(xmlHttp);
                                }
                                if (successCallback) {
                                    successCallback(xmlHttp);
                                }
                            } else {
                                var msg = "AjaxAppender.append: XMLHttpRequest request to URL " + url + " returned status code " + xmlHttp.status;
                                handleError(msg);
                                if (failCallback) {
                                    failCallback(msg);
                                }
                            }
                            xmlHttp.onreadystatechange = emptyFunction;
                            xmlHttp = null;
                        }
                    };
                    xmlHttp.open("POST", url, true);
                    try {
                        xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                    }
                    catch (headerEx) {
                        var msg = "AjaxAppender.append: your browser's XMLHttpRequest implementation" + " does not support setRequestHeader, therefore cannot post data. AjaxAppender disabled";
                        handleError(msg);
                        isSupported = false;
                        if (failCallback) {
                            failCallback(msg);
                        }
                        return;
                    }
                    xmlHttp.send(postData);
                }
            }
            catch (ex) {
                var msg = "AjaxAppender.append: error sending log message to " + url;
                handleError(msg, ex);
                if (failCallback) {
                    failCallback(msg + ". Details: " + getExceptionStringRep(ex));
                }
            }
        }
        this.append = function (loggingEvent) {
            if (isSupported) {
                if (!initialized) {
                    init();
                }
                queuedLoggingEvents.push(loggingEvent);
                var actualBatchSize = this.getLayout().allowBatching() ? batchSize : 1;
                if (queuedLoggingEvents.length >= actualBatchSize) {
                    var currentLoggingEvent;
                    var postData = "";
                    var batchedLoggingEvents = [];
                    while ((currentLoggingEvent = queuedLoggingEvents.shift())) {
                        batchedLoggingEvents.push(currentLoggingEvent);
                    }
                    queuedRequests.push(batchedLoggingEvents);
                    if (!timed) {
                        if (!waitForResponse || (waitForResponse && !sending)) {
                            sendAll();
                        }
                    }
                }
            }
        };
        function init() {
            initialized = true;
            if (timed) {
                scheduleSending();
            }
        }
    };
    AjaxAppender.prototype = new Appender();
    AjaxAppender.prototype.defaults = {waitForResponse:false, timed:false, timerInterval:1000, batchSize:1, requestSuccessCallback:null, failCallback:null};
    AjaxAppender.prototype.layout = new HttpPostDataLayout();
    AjaxAppender.prototype.toString = function () {
        return "[AjaxAppender]";
    };
    log4javascript.AjaxAppender = AjaxAppender;
    (function () {
        var getConsoleHtmlLines = function () {
            return ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">", "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">", "<head>", "<title>log4javascript</title>", "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />", "<script type=\"text/javascript\">", "//<![CDATA[", "var loggingEnabled=true;function toggleLoggingEnabled(){setLoggingEnabled($(\"enableLogging\").checked)}function setLoggingEnabled(enable){loggingEnabled=enable}var newestAtTop=false;function setNewestAtTop(isNewestAtTop){var oldNewestAtTop=newestAtTop;newestAtTop=Boolean(isNewestAtTop);if(oldNewestAtTop!=newestAtTop){var lc=getLogContainer();var numberOfEntries=lc.childNodes.length;var node=null;var logContainerChildNodes=[];while((node=lc.firstChild)){lc.removeChild(node);logContainerChildNodes.push(node)}while((node=logContainerChildNodes.pop())){lc.appendChild(node)}if(currentSearch){var currentMatch=currentSearch.matches[currentMatchIndex];var matchIndex=0;var matches=[];var actOnLogEntry=function(logEntry){var logEntryMatches=logEntry.getSearchMatches();for(var i=0;i<logEntryMatches.length;i++){matches[matchIndex]=logEntryMatches[i];if(currentMatch&&logEntryMatches[i].equals(currentMatch)){currentMatchIndex=matchIndex}matchIndex++}};var i;if(newestAtTop){for(i=logEntries.length-1;i>=0;i--){actOnLogEntry(logEntries[i])}}else{for(i=0;i<logEntries.length;i++){actOnLogEntry(logEntries[i])}}currentSearch.matches=matches;if(currentMatch){currentMatch.setCurrent()}}else if(scrollToLatest){doScrollToLatest()}}$(\"newestAtTop\").checked=isNewestAtTop}function toggleNewestAtTop(){var isNewestAtTop=$(\"newestAtTop\").checked;setNewestAtTop(isNewestAtTop)}var scrollToLatest=true;function setScrollToLatest(isScrollToLatest){scrollToLatest=isScrollToLatest;if(scrollToLatest){doScrollToLatest()}$(\"scrollToLatest\").checked=isScrollToLatest}function toggleScrollToLatest(){var isScrollToLatest=$(\"scrollToLatest\").checked;setScrollToLatest(isScrollToLatest)}function doScrollToLatest(){var l=getLogContainer();if(typeof l.scrollTop!=\"undefined\"){if(newestAtTop){l.scrollTop=0}else{var latestLogEntry=l.lastChild;if(latestLogEntry){l.scrollTop=l.scrollHeight}}}}var maxMessages=null;function setMaxMessages(max){maxMessages=max;pruneLogEntries()}var logQueuedEventsTimer=null;var logEntries=[];var isCssWrapSupported;var renderDelay=100;function log(logLevel,formattedMessage){if(loggingEnabled){var logEntry=new LogEntry(logLevel,formattedMessage);logEntries.push(logEntry);if(loaded){if(logQueuedEventsTimer!==null){clearTimeout(logQueuedEventsTimer)}setTimeout(renderQueuedLogEntries,renderDelay)}}}function renderQueuedLogEntries(){logQueuedEventsTimer=null;var pruned=pruneLogEntries();var initiallyHasMatches=currentSearch?currentSearch.hasMatches():false;for(var i=0;i<logEntries.length;i++){if(!logEntries[i].isRendered){logEntries[i].render();logEntries[i].appendToLog();if(currentSearch){currentSearch.applyTo(logEntries[i])}}}if(currentSearch){if(pruned){if(currentSearch.hasMatches()){if(currentMatchIndex===null){setCurrentMatchIndex(0)}displayMatches()}else{displayNoMatches()}}else if(!initiallyHasMatches&&currentSearch.hasMatches()){setCurrentMatchIndex(0);displayMatches()}}if(scrollToLatest){doScrollToLatest()}}function pruneLogEntries(){if((maxMessages!==null)&&(logEntries.length>maxMessages)){var numberToDelete=logEntries.length-maxMessages;for(var i=0;i<numberToDelete;i++){logEntries[i].remove()}logEntries=array_removeFromStart(logEntries,numberToDelete);if(currentSearch){currentSearch.removePrunedMatches()}return true}return false}function LogEntry(level,formattedMessage){this.level=level;this.formattedMessage=formattedMessage;this.isRendered=false}LogEntry.prototype={render:function(){this.mainDiv=document.createElement(\"div\");this.mainDiv.className=\"logentry \"+this.level.name;if(isCssWrapSupported){this.mainDiv.appendChild(document.createTextNode(this.formattedMessage))}else{this.formattedMessage=this.formattedMessage.replace(/\\r\\n/g,\"\\r\");this.unwrappedPre=this.mainDiv.appendChild(document.createElement(\"pre\"));this.unwrappedPre.appendChild(document.createTextNode(this.formattedMessage));this.unwrappedPre.className=\"unwrapped\";this.wrappedSpan=this.mainDiv.appendChild(document.createElement(\"span\"));this.wrappedSpan.appendChild(document.createTextNode(this.formattedMessage));this.wrappedSpan.className=\"wrapped\"}this.content=this.formattedMessage;this.isRendered=true},appendToLog:function(){var lc=getLogContainer();if(newestAtTop&&lc.hasChildNodes()){lc.insertBefore(this.mainDiv,lc.firstChild)}else{getLogContainer().appendChild(this.mainDiv)}},setContent:function(content){if(content!=this.content){if(getLogContainer().currentStyle){if(content===this.formattedMessage){this.unwrappedPre.innerHTML=\"\";this.unwrappedPre.appendChild(document.createTextNode(this.formattedMessage));this.wrappedSpan.innerHTML=\"\";this.wrappedSpan.appendChild(document.createTextNode(this.formattedMessage))}else{content=content.replace(/\\r\\n/g,\"\\r\");this.unwrappedPre.innerHTML=content;this.wrappedSpan.innerHTML=content}}else{if(content===this.formattedMessage){this.mainDiv.innerHTML=\"\";this.mainDiv.appendChild(document.createTextNode(this.formattedMessage))}else{this.mainDiv.innerHTML=content}}this.content=content}},getSearchMatches:function(){var matches=[];if(isCssWrapSupported){var els=getElementsByClass(this.mainDiv,\"searchterm\",\"span\");for(var i=0;i<els.length;i++){matches[i]=new Match(this.level,els[i])}}else{var unwrappedEls=getElementsByClass(this.unwrappedPre,\"searchterm\",\"span\");var wrappedEls=getElementsByClass(this.wrappedSpan,\"searchterm\",\"span\");for(i=0;i<unwrappedEls.length;i++){matches[i]=new Match(this.level,null,unwrappedEls[i],wrappedEls[i])}}return matches},remove:function(){if(this.isRendered){this.mainDiv.parentNode.removeChild(this.mainDiv);this.mainDiv=null}}};function mainPageReloaded(){var separator=document.createElement(\"div\");separator.className=\"separator\";separator.innerHTML=\"&nbsp;\";getLogContainer().appendChild(separator)}window.onload=function(){isCssWrapSupported=(typeof getLogContainer().currentStyle==\"undefined\");setLogContainerHeight();toggleLoggingEnabled();toggleSearchEnabled();toggleSearchFilter();toggleSearchHighlight();applyFilters();toggleWrap();toggleNewestAtTop();toggleScrollToLatest();renderQueuedLogEntries();loaded=true;setTimeout(setLogContainerHeight,20);if(window!=top){$(\"closeButton\").style.display=\"none\"}};var loaded=false;var logLevels=[\"TRACE\",\"DEBUG\",\"INFO\",\"WARN\",\"ERROR\",\"FATAL\"];function getCheckBox(logLevel){return $(\"switch_\"+logLevel)}function getLogContainer(){return $(\"log\")}function applyFilters(){for(var i=0;i<logLevels.length;i++){if(getCheckBox(logLevels[i]).checked){addClass(getLogContainer(),logLevels[i])}else{removeClass(getLogContainer(),logLevels[i])}}updateSearchFromFilters()}function toggleAllLevels(){var turnOn=$(\"switch_ALL\").checked;for(var i=0;i<logLevels.length;i++){getCheckBox(logLevels[i]).checked=turnOn;if(turnOn){addClass(getLogContainer(),logLevels[i])}else{removeClass(getLogContainer(),logLevels[i])}}}function checkAllLevels(){for(var i=0;i<logLevels.length;i++){if(!getCheckBox(logLevels[i]).checked){getCheckBox(\"ALL\").checked=false;return}}getCheckBox(\"ALL\").checked=true}function clearLog(){getLogContainer().innerHTML=\"\";logEntries=[];doSearch()}function toggleWrap(){var enable=$(\"wrap\").checked;if(enable){addClass(getLogContainer(),\"wrap\")}else{removeClass(getLogContainer(),\"wrap\")}refreshCurrentMatch()}var searchTimer=null;function scheduleSearch(){try{clearTimeout(searchTimer)}catch(ex){}searchTimer=setTimeout(doSearch,500)}function Search(searchTerm,isRegex,searchRegex,isCaseSensitive){this.searchTerm=searchTerm;this.isRegex=isRegex;this.searchRegex=searchRegex;this.isCaseSensitive=isCaseSensitive;this.matches=[]}Search.prototype={hasMatches:function(){return this.matches.length>0},hasVisibleMatches:function(){if(this.hasMatches()){for(var i=0;i<=this.matches.length;i++){if(this.matches[i].isVisible()){return true}}}return false},match:function(logEntry){var entryText=logEntry.formattedMessage;var matchesSearch=false;if(this.isRegex){matchesSearch=this.searchRegex.test(entryText)}else if(this.isCaseSensitive){matchesSearch=(entryText.indexOf(this.searchTerm)>-1)}else{matchesSearch=(entryText.toLowerCase().indexOf(this.searchTerm.toLowerCase())>-1)}return matchesSearch},getNextVisibleMatchIndex:function(){for(var i=currentMatchIndex+1;i<this.matches.length;i++){if(this.matches[i].isVisible()){return i}}for(var i=0;i<=currentMatchIndex;i++){if(this.matches[i].isVisible()){return i}}return-1},getPreviousVisibleMatchIndex:function(){for(var i=currentMatchIndex-1;i>=0;i--){if(this.matches[i].isVisible()){return i}}for(var i=this.matches.length-1;i>=currentMatchIndex;i--){if(this.matches[i].isVisible()){return i}}return-1},applyTo:function(logEntry){var doesMatch=this.match(logEntry);if(doesMatch){replaceClass(logEntry.mainDiv,\"searchmatch\",\"searchnonmatch\");var logEntryContent;if(this.isRegex){var flags=this.isCaseSensitive?\"g\":\"gi\";var capturingRegex=new RegExp(\"(\"+this.searchRegex.source+\")\",flags);logEntryContent=logEntry.formattedMessage.replace(capturingRegex,\"<span class=\\\"searchterm\\\">$1</span>\")}else{logEntryContent=\"\";var searchTermReplacementStartTag=\"<span class=\\\"searchterm\\\">\";var searchTermReplacementEndTag=\"</span>\";var searchTermReplacementLength=searchTermReplacementStartTag.length+this.searchTerm.length+searchTermReplacementEndTag.length;var searchTermLength=this.searchTerm.length;var startIndex=0;var searchIndex;var searchTermLowerCase=this.searchTerm.toLowerCase();var logTextLowerCase=logEntry.formattedMessage.toLowerCase();while((searchIndex=logTextLowerCase.indexOf(searchTermLowerCase,startIndex))>-1){var searchTermReplacement=searchTermReplacementStartTag+logEntry.formattedMessage.substr(searchIndex,this.searchTerm.length)+searchTermReplacementEndTag;logEntryContent+=logEntry.formattedMessage.substring(startIndex,searchIndex)+searchTermReplacement;startIndex=searchIndex+searchTermLength}logEntryContent+=logEntry.formattedMessage.substr(startIndex)}logEntry.setContent(logEntryContent);var logEntryMatches=logEntry.getSearchMatches();this.matches=this.matches.concat(logEntryMatches)}else{replaceClass(logEntry.mainDiv,\"searchnonmatch\",\"searchmatch\");logEntry.setContent(logEntry.formattedMessage)}return doesMatch},removePrunedMatches:function(){var matchesToRemoveCount=0;var currentMatchRemoved=false;for(var i=0;i<this.matches.length;i++){if(this.matches[i].isOrphan()){this.matches[i].remove();if(i===currentMatchIndex){currentMatchRemoved=true}matchesToRemoveCount++}}if(matchesToRemoveCount>0){array_removeFromStart(this.matches,matchesToRemoveCount);var newMatchIndex=currentMatchRemoved?0:currentMatchIndex-matchesToRemoveCount;if(this.hasMatches()){setCurrentMatchIndex(newMatchIndex)}else{currentMatchIndex=null}}}};function getPageOffsetTop(el){var currentEl=el;var y=0;while(currentEl){y+=currentEl.offsetTop;currentEl=currentEl.offsetParent}return y}function scrollIntoView(el){getLogContainer().scrollLeft=el.offsetLeft;getLogContainer().scrollTop=getPageOffsetTop(el)-getToolBarsHeight()}function Match(logEntryLevel,spanInMainDiv,spanInUnwrappedPre,spanInWrappedSpan){this.logEntryLevel=logEntryLevel;this.spanInMainDiv=spanInMainDiv;if(!isCssWrapSupported){this.spanInUnwrappedPre=spanInUnwrappedPre;this.spanInWrappedSpan=spanInWrappedSpan}this.mainSpan=isCssWrapSupported?spanInMainDiv:spanInUnwrappedPre}Match.prototype={equals:function(match){return this.mainSpan===match.mainSpan},setCurrent:function(){if(isCssWrapSupported){addClass(this.spanInMainDiv,\"currentmatch\");scrollIntoView(this.spanInMainDiv)}else{addClass(this.spanInUnwrappedPre,\"currentmatch\");addClass(this.spanInWrappedSpan,\"currentmatch\");var elementToScroll=$(\"wrap\").checked?this.spanInWrappedSpan:this.spanInUnwrappedPre;scrollIntoView(elementToScroll)}},setNotCurrent:function(){if(isCssWrapSupported){removeClass(this.spanInMainDiv,\"currentmatch\")}else{removeClass(this.spanInUnwrappedPre,\"currentmatch\");removeClass(this.spanInWrappedSpan,\"currentmatch\")}},isOrphan:function(){return isOrphan(this.mainSpan)},isVisible:function(){return getCheckBox(this.logEntryLevel).checked},remove:function(){if(isCssWrapSupported){this.spanInMainDiv=null}else{this.spanInUnwrappedPre=null;this.spanInWrappedSpan=null}}};var currentSearch=null;var currentMatchIndex=null;function doSearch(){var searchBox=$(\"searchBox\");var searchTerm=searchBox.value;var isRegex=$(\"searchRegex\").checked;var isCaseSensitive=$(\"searchCaseSensitive\").checked;var i;if(searchTerm===\"\"){$(\"searchReset\").disabled=true;$(\"searchNav\").style.display=\"none\";removeClass(document.body,\"searching\");removeClass(searchBox,\"hasmatches\");removeClass(searchBox,\"nomatches\");for(i=0;i<logEntries.length;i++){removeClass(logEntries[i].mainDiv,\"searchmatch\");removeClass(logEntries[i].mainDiv,\"searchnonmatch\");logEntries[i].setContent(logEntries[i].formattedMessage)}currentSearch=null;setLogContainerHeight()}else{$(\"searchReset\").disabled=false;$(\"searchNav\").style.display=\"block\";var searchRegex;var regexValid;if(isRegex){try{searchRegex=isCaseSensitive?new RegExp(searchTerm,\"g\"):new RegExp(searchTerm,\"gi\");regexValid=true;replaceClass(searchBox,\"validregex\",\"invalidregex\");searchBox.title=\"Valid regex\"}catch(ex){regexValid=false;replaceClass(searchBox,\"invalidregex\",\"validregex\");searchBox.title=\"Invalid regex: \"+(ex.message?ex.message:(ex.description?ex.description:\"unknown error\"));return}}else{searchBox.title=\"\";removeClass(searchBox,\"validregex\");removeClass(searchBox,\"invalidregex\")}addClass(document.body,\"searching\");currentSearch=new Search(searchTerm,isRegex,searchRegex,isCaseSensitive);for(i=0;i<logEntries.length;i++){currentSearch.applyTo(logEntries[i])}setLogContainerHeight();if(currentSearch.hasMatches()){setCurrentMatchIndex(0);displayMatches()}else{displayNoMatches()}}}function updateSearchFromFilters(){if(currentSearch&&currentSearch.hasMatches()){var currentMatch=currentSearch.matches[currentMatchIndex];if(currentMatch.isVisible()){displayMatches();setCurrentMatchIndex(currentMatchIndex)}else{currentMatch.setNotCurrent();var nextVisibleMatchIndex=currentSearch.getNextVisibleMatchIndex();if(nextVisibleMatchIndex>-1){setCurrentMatchIndex(nextVisibleMatchIndex);displayMatches()}else{displayNoMatches()}}}}function refreshCurrentMatch(){if(currentSearch&&currentSearch.hasMatches()){setCurrentMatchIndex(currentMatchIndex)}}function displayMatches(){replaceClass($(\"searchBox\"),\"hasmatches\",\"nomatches\");$(\"searchBox\").title=\"\"+currentSearch.matches.length+\" matches found\";$(\"searchNav\").style.display=\"block\";setLogContainerHeight()}function displayNoMatches(){replaceClass($(\"searchBox\"),\"nomatches\",\"hasmatches\");$(\"searchBox\").title=\"No matches found\";$(\"searchNav\").style.display=\"none\";setLogContainerHeight()}function toggleSearchEnabled(enable){enable=(typeof enable==\"undefined\")?!$(\"searchDisable\").checked:enable;$(\"searchBox\").disabled=!enable;$(\"searchReset\").disabled=!enable;$(\"searchRegex\").disabled=!enable;$(\"searchNext\").disabled=!enable;$(\"searchPrevious\").disabled=!enable;$(\"searchCaseSensitive\").disabled=!enable;$(\"searchNav\").style.display=(enable&&($(\"searchBox\").value!==\"\"))?\"block\":\"none\";if(enable){removeClass($(\"search\"),\"greyedout\");addClass(document.body,\"searching\");if($(\"searchHighlight\").checked){addClass(getLogContainer(),\"searchhighlight\")}else{removeClass(getLogContainer(),\"searchhighlight\")}if($(\"searchFilter\").checked){addClass(getLogContainer(),\"searchfilter\")}else{removeClass(getLogContainer(),\"searchfilter\")}$(\"searchDisable\").checked=!enable}else{addClass($(\"search\"),\"greyedout\");removeClass(document.body,\"searching\");removeClass(getLogContainer(),\"searchhighlight\");removeClass(getLogContainer(),\"searchfilter\")}setLogContainerHeight()}function toggleSearchFilter(){var enable=$(\"searchFilter\").checked;if(enable){addClass(getLogContainer(),\"searchfilter\")}else{removeClass(getLogContainer(),\"searchfilter\")}refreshCurrentMatch()}function toggleSearchHighlight(){var enable=$(\"searchHighlight\").checked;if(enable){addClass(getLogContainer(),\"searchhighlight\")}else{removeClass(getLogContainer(),\"searchhighlight\")}}function clearSearch(){$(\"searchBox\").value=\"\";doSearch()}function searchNext(){try{if(currentSearch!==null&&currentMatchIndex!==null){currentSearch.matches[currentMatchIndex].setNotCurrent();var nextMatchIndex=currentSearch.getNextVisibleMatchIndex();if(nextMatchIndex>currentMatchIndex||confirm(\"Reached the end of the page. Start from the top?\")){setCurrentMatchIndex(nextMatchIndex)}}}catch(err){alert(\"currentMatchIndex is \"+currentMatchIndex)}}function searchPrevious(){if(currentSearch!==null&&currentMatchIndex!==null){currentSearch.matches[currentMatchIndex].setNotCurrent();var previousMatchIndex=currentSearch.getPreviousVisibleMatchIndex();if(previousMatchIndex<currentMatchIndex||confirm(\"Reached the start of the page. Continue from the bottom?\")){setCurrentMatchIndex(previousMatchIndex)}}}function setCurrentMatchIndex(index){currentMatchIndex=index;currentSearch.matches[currentMatchIndex].setCurrent()}function addClass(el,cssClass){if(!hasClass(el,cssClass)){if(el.className){el.className+=\" \"+cssClass}else{el.className=cssClass}}}function hasClass(el,cssClass){if(el.className){var classNames=el.className.split(\" \");return array_contains(classNames,cssClass)}return false}function removeClass(el,cssClass){if(hasClass(el,cssClass)){var existingClasses=el.className.split(\" \");var newClasses=[];for(var i=0;i<existingClasses.length;i++){if(existingClasses[i]!=cssClass){newClasses[newClasses.length]=existingClasses[i]}}el.className=newClasses.join(\" \")}}function replaceClass(el,newCssClass,oldCssClass){removeClass(el,oldCssClass);addClass(el,newCssClass)}function getElementsByClass(el,cssClass,tagName){var elements=el.getElementsByTagName(tagName);var matches=[];for(var i=0;i<elements.length;i++){if(hasClass(elements[i],cssClass)){matches.push(elements[i])}}return matches}function $(id){return document.getElementById(id)}function isOrphan(node){var currentNode=node;while(currentNode){if(currentNode==document.body){return false}currentNode=currentNode.parentNode}return true}function getWindowWidth(){if(window.innerWidth){return window.innerWidth}else if(document.documentElement&&document.documentElement.clientWidth){return document.documentElement.clientWidth}else if(document.body){return document.body.clientWidth}return 0}function getWindowHeight(){if(window.innerHeight){return window.innerHeight}else if(document.documentElement&&document.documentElement.clientHeight){return document.documentElement.clientHeight}else if(document.body){return document.body.clientHeight}return 0}function getToolBarsHeight(){return $(\"switches\").offsetHeight}function setLogContainerHeight(){var windowHeight=getWindowHeight();$(\"body\").style.height=getWindowHeight()+\"px\";getLogContainer().style.height=\"\"+(windowHeight-getToolBarsHeight())+\"px\"}window.onresize=setLogContainerHeight;if(!Array.prototype.push){Array.prototype.push=function(){for(var i=0;i<arguments.length;i++){this[this.length]=arguments[i]}return this.length}}if(!Array.prototype.pop){Array.prototype.pop=function(){if(this.length>0){var val=this[this.length-1];this.length=this.length-1;return val}}}if(!Array.prototype.shift){Array.prototype.shift=function(){if(this.length>0){var firstItem=this[0];for(var i=0;i<this.length-1;i++){this[i]=this[i+1]}this.length=this.length-1;return firstItem}}}function array_removeFromStart(array,numberToRemove){if(Array.prototype.splice){array.splice(0,numberToRemove)}else{for(var i=numberToRemove;i<array.length;i++){array[i-numberToRemove]=array[i]}array.length=array.length-numberToRemove}return array}function array_contains(arr,val){for(var i=0;i<arr.length;i++){if(arr[i]==val){return true}}return false}", "//]]>", "</script>", "<style type=\"text/css\">", "body{background-color:white;color:black;padding:0px;margin:0px;font-family:tahoma,verdana,arial,helvetica,sans-serif;overflow:hidden}div#switchesContainer input{margin-bottom:0px}div#switches div.toolbar{border-top:solid #ffffff 1px;border-bottom:solid #aca899 1px;background-color:#f1efe7;padding:3px 5px;font-size:68.75%}div#switches div.toolbar,div#search input{font-family:tahoma,verdana,arial,helvetica,sans-serif}div#switches input.button{padding:0px 5px;font-size:100%}div#switches input#clearButton{margin-left:20px}div#levels label{font-weight:bold}div#levels label,div#options label{margin-right:5px}div#levels label#wrapLabel{font-weight:normal}div#search{padding:5px 0px}div#search label{margin-right:10px}div#search label.searchboxlabel{margin-right:0px}div#search input{font-size:100%}div#search input.validregex{color:green}div#search input.invalidregex{color:red}div#search input.nomatches{color:white;background-color:#ff6666}div#search input.nomatches{color:white;background-color:#ff6666}*.greyedout{color:gray}*.greyedout *.alwaysenabled{color:black}div#log{font-family:Courier New,Courier;font-size:75%;width:100%;overflow:auto}*.logentry{overflow:visible;display:none;white-space:pre}*.logentry pre.unwrapped{display:inline}*.logentry span.wrapped{display:none}body.searching *.logentry span.currentmatch{color:white !important;background-color:green !important}body.searching div.searchhighlight *.logentry span.searchterm{color:black;background-color:yellow}div.wrap *.logentry{white-space:normal !important;border-width:0px 0px 1px 0px;border-color:#dddddd;border-style:dotted}div.wrap *.logentry pre.unwrapped{display:none}div.wrap *.logentry span.wrapped{display:inline}div.searchfilter *.searchnonmatch{display:none !important}div#log *.TRACE,label#label_TRACE{color:#666666}div#log *.DEBUG,label#label_DEBUG{color:green}div#log *.INFO,label#label_INFO{color:#000099}div#log *.WARN,label#label_WARN{color:#999900}div#log *.ERROR,label#label_ERROR{color:red}div#log *.FATAL,label#label_FATAL{color:#660066}div.TRACE#log *.TRACE,div.DEBUG#log *.DEBUG,div.INFO#log *.INFO,div.WARN#log *.WARN,div.ERROR#log *.ERROR,div.FATAL#log *.FATAL{display:block}div#log div.separator{background-color:#cccccc;margin:5px 0px;line-height:1px}", "</style>", "</head>", "<body id=\"body\">", "<div id=\"switchesContainer\">", "<div id=\"switches\">", "<div id=\"levels\" class=\"toolbar\">", "Filters:", "<input type=\"checkbox\" id=\"switch_TRACE\" onclick=\"applyFilters(); checkAllLevels()\" checked=\"checked\" title=\"Show/hide trace messages\" /><label for=\"switch_TRACE\" id=\"label_TRACE\">trace</label>", "<input type=\"checkbox\" id=\"switch_DEBUG\" onclick=\"applyFilters(); checkAllLevels()\" checked=\"checked\" title=\"Show/hide debug messages\" /><label for=\"switch_DEBUG\" id=\"label_DEBUG\">debug</label>", "<input type=\"checkbox\" id=\"switch_INFO\" onclick=\"applyFilters(); checkAllLevels()\" checked=\"checked\" title=\"Show/hide info messages\" /><label for=\"switch_INFO\" id=\"label_INFO\">info</label>", "<input type=\"checkbox\" id=\"switch_WARN\" onclick=\"applyFilters(); checkAllLevels()\" checked=\"checked\" title=\"Show/hide warn messages\" /><label for=\"switch_WARN\" id=\"label_WARN\">warn</label>", "<input type=\"checkbox\" id=\"switch_ERROR\" onclick=\"applyFilters(); checkAllLevels()\" checked=\"checked\" title=\"Show/hide error messages\" /><label for=\"switch_ERROR\" id=\"label_ERROR\">error</label>", "<input type=\"checkbox\" id=\"switch_FATAL\" onclick=\"applyFilters(); checkAllLevels()\" checked=\"checked\" title=\"Show/hide fatal messages\" /><label for=\"switch_FATAL\" id=\"label_FATAL\">fatal</label>", "<input type=\"checkbox\" id=\"switch_ALL\" onclick=\"toggleAllLevels(); applyFilters()\" checked=\"checked\" title=\"Show/hide all messages\" /><label for=\"switch_ALL\" id=\"label_ALL\">all</label>", "</div>", "<div id=\"search\" class=\"toolbar\">", "<label for=\"searchBox\" class=\"searchboxlabel\">Search:</label> <input type=\"text\" id=\"searchBox\" onclick=\"toggleSearchEnabled(true)\" onkeyup=\"scheduleSearch()\" size=\"20\" />", "<input type=\"button\" id=\"searchReset\" disabled=\"disabled\" value=\"Reset\" onclick=\"clearSearch()\" class=\"button\" title=\"Reset the search\" />", "<input type=\"checkbox\" id=\"searchRegex\" onclick=\"doSearch()\" title=\"If checked, search is treated as a regular expression\" /><label for=\"searchRegex\">Regex</label>", "<input type=\"checkbox\" id=\"searchCaseSensitive\" onclick=\"doSearch()\" title=\"If checked, search is case sensitive\" /><label for=\"searchCaseSensitive\">Match case</label>", "<input type=\"checkbox\" id=\"searchDisable\" onclick=\"toggleSearchEnabled()\" title=\"Enable/disable search\" /><label for=\"searchDisable\" class=\"alwaysenabled\">Disable</label>", "<div id=\"searchNav\">", "<input type=\"button\" id=\"searchNext\" disabled=\"disabled\" value=\"Next\" onclick=\"searchNext()\" class=\"button\" title=\"Go to the next matching log entry\" />", "<input type=\"button\" id=\"searchPrevious\" disabled=\"disabled\" value=\"Previous\" onclick=\"searchPrevious()\" class=\"button\" title=\"Go to the previous matching log entry\" />", "<input type=\"checkbox\" id=\"searchFilter\" onclick=\"toggleSearchFilter()\" title=\"If checked, non-matching log entries are filtered out\" /><label for=\"searchFilter\">Filter</label>", "<input type=\"checkbox\" id=\"searchHighlight\" onclick=\"toggleSearchHighlight()\" title=\"Highlight matched search terms\" /><label for=\"searchHighlight\" class=\"alwaysenabled\">Highlight all</label>", "</div>", "</div>", "<div id=\"options\" class=\"toolbar\">", "Options:", "<input type=\"checkbox\" id=\"enableLogging\" onclick=\"toggleLoggingEnabled()\" checked=\"checked\" title=\"Enable/disable logging\" /><label for=\"enableLogging\" id=\"wrapLabel\">Log</label>", "<input type=\"checkbox\" id=\"wrap\" onclick=\"toggleWrap()\" title=\"Enable / disable word wrap\" /><label for=\"wrap\" id=\"wrapLabel\">Wrap</label>", "<input type=\"checkbox\" id=\"newestAtTop\" onclick=\"toggleNewestAtTop()\" title=\"If checked, causes newest messages to appear at the top\" /><label for=\"newestAtTop\" id=\"newestAtTopLabel\">Newest at the top</label>", "<input type=\"checkbox\" id=\"scrollToLatest\" onclick=\"toggleScrollToLatest()\" checked=\"checked\" title=\"If checked, window automatically scrolls to a new message when it is added\" /><label for=\"scrollToLatest\" id=\"scrollToLatestLabel\">Scroll to latest</label>", "<input type=\"button\" id=\"clearButton\" value=\"Clear\" onclick=\"clearLog()\" class=\"button\" title=\"Clear all log messages\"  />", "<input type=\"button\" id=\"closeButton\" value=\"Close\" onclick=\"window.close()\" class=\"button\" title=\"Close the window\" />", "</div>", "</div>", "</div>", "<div id=\"log\" class=\"TRACE DEBUG INFO WARN ERROR FATAL\"></div>", "</body>", "</html>"];
        };
        function ConsoleAppender() {
        }
        var consoleAppenderIdCounter = 1;
        ConsoleAppender.prototype = new Appender();
        ConsoleAppender.prototype.create = function (inPage, containerElement, layout, lazyInit, focusConsoleWindow, useOldPopUp, complainAboutPopUpBlocking, newestMessageAtTop, scrollToLatestMessage, initiallyMinimized, width, height, reopenWhenClosed, maxMessages) {
            var appender = this;
            if (layout) {
                this.setLayout(layout);
            } else {
                this.setLayout(this.defaults.layout);
            }
            var initialized = false;
            var consoleWindowLoaded = false;
            var queuedLoggingEvents = [];
            var isSupported = true;
            var consoleAppenderId = consoleAppenderIdCounter++;
            lazyInit = extractBooleanFromParam(lazyInit, true);
            newestMessageAtTop = extractBooleanFromParam(newestMessageAtTop, this.defaults.newestMessageAtTop);
            scrollToLatestMessage = extractBooleanFromParam(scrollToLatestMessage, this.defaults.scrollToLatestMessage);
            width = width ? width : this.defaults.width;
            height = height ? height : this.defaults.height;
            maxMessages = maxMessages ? maxMessages : this.defaults.maxMessages;
            var init, safeToAppend, getConsoleWindow;
            var appenderName = inPage ? "InPageAppender" : "PopUpAppender";
            var checkCanConfigure = function (configOptionName) {
                if (initialized) {
                    handleError(appenderName + ": configuration option '" + configOptionName + "' may not be set after the appender has been initialized");
                    return false;
                }
                return true;
            };
            this.isNewestMessageAtTop = function () {
                return newestMessageAtTop;
            };
            this.setNewestMessageAtTop = function (newestMessageAtTopParam) {
                newestMessageAtTop = bool(newestMessageAtTopParam);
                if (consoleWindowLoaded && isSupported) {
                    getConsoleWindow().setNewestAtTop(newestMessageAtTop);
                }
            };
            this.isScrollToLatestMessage = function () {
                return scrollToLatestMessage;
            };
            this.setScrollToLatestMessage = function (scrollToLatestMessageParam) {
                scrollToLatestMessage = bool(scrollToLatestMessageParam);
                if (consoleWindowLoaded && isSupported) {
                    getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
                }
            };
            this.getWidth = function () {
                return width;
            };
            this.setWidth = function (widthParam) {
                if (checkCanConfigure("width")) {
                    width = extractStringFromParam(widthParam, width);
                }
            };
            this.getHeight = function () {
                return height;
            };
            this.setHeight = function (heightParam) {
                if (checkCanConfigure("height")) {
                    height = extractStringFromParam(heightParam, height);
                }
            };
            this.getMaxMessages = function () {
                return maxMessages;
            };
            this.setMaxMessages = function (maxMessagesParam) {
                maxMessages = extractIntFromParam(maxMessagesParam, maxMessages);
                if (consoleWindowLoaded && isSupported) {
                    getConsoleWindow().setMaxMessages(maxMessages);
                }
            };
            this.append = function (loggingEvent) {
                if (isSupported) {
                    queuedLoggingEvents.push(loggingEvent);
                    var isSafeToAppend = safeToAppend();
                    if (!initialized || (consoleClosed && reopenWhenClosed)) {
                        init();
                    }
                    if (safeToAppend()) {
                        appendQueuedLoggingEvents();
                    }
                }
            };
            var appendQueuedLoggingEvents = function (loggingEvent) {
                while (queuedLoggingEvents.length > 0) {
                    var currentLoggingEvent = queuedLoggingEvents.shift();
                    var formattedMessage = appender.getLayout().format(currentLoggingEvent);
                    if (appender.getLayout().ignoresThrowable()) {
                        formattedMessage += currentLoggingEvent.getThrowableStrRep();
                    }
                    getConsoleWindow().log(currentLoggingEvent.level, formattedMessage);
                }
                if (focusConsoleWindow) {
                    getConsoleWindow().focus();
                }
            };
            var writeHtml = function (doc) {
                var lines = getConsoleHtmlLines();
                doc.open();
                for (var i = 0; i < lines.length; i++) {
                    doc.writeln(lines[i]);
                }
                doc.close();
            };
            var consoleClosed = false;
            var pollConsoleWindow = function (windowTest, successCallback, errorMessage) {
                function pollConsoleWindowLoaded() {
                    try {
                        if (consoleClosed) {
                            clearInterval(poll);
                        }
                        if (windowTest(getConsoleWindow())) {
                            clearInterval(poll);
                            successCallback();
                        }
                    }
                    catch (ex) {
                        clearInterval(poll);
                        isSupported = false;
                        handleError(errorMessage, ex);
                    }
                }
                var poll = setInterval(pollConsoleWindowLoaded, 100);
            };
            if (inPage) {
                if (!containerElement || !containerElement.appendChild) {
                    isSupported = false;
                    handleError("InPageAppender.init: a container DOM element must be supplied for the console window");
                    return;
                }
                initiallyMinimized = extractBooleanFromParam(initiallyMinimized, appender.defaults.initiallyMinimized);
                this.isInitiallyMinimized = function () {
                    return initiallyMinimized;
                };
                this.setInitiallyMinimized = function (initiallyMinimizedParam) {
                    if (checkCanConfigure("initiallyMinimized")) {
                        initiallyMinimized = bool(initiallyMinimizedParam);
                    }
                };
                var minimized = false;
                var iframeContainerDiv;
                var iframeId = uniqueId + "_InPageAppender_" + consoleAppenderId;
                this.hide = function () {
                    iframeContainerDiv.style.display = "none";
                    minimized = true;
                };
                this.show = function () {
                    iframeContainerDiv.style.display = "block";
                    minimized = false;
                };
                this.isVisible = function () {
                    return !minimized;
                };
                this.close = function () {
                    if (!consoleClosed) {
                        iframeContainerDiv.parentNode.removeChild(iframeContainerDiv);
                        consoleClosed = true;
                    }
                };
                init = function () {
                    var initErrorMessage = "InPageAppender.init: unable to create console iframe";
                    function finalInit() {
                        try {
                            getConsoleWindow().setNewestAtTop(newestMessageAtTop);
                            getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
                            getConsoleWindow().setMaxMessages(maxMessages);
                            consoleWindowLoaded = true;
                            appendQueuedLoggingEvents();
                            if (initiallyMinimized) {
                                appender.hide();
                            }
                        }
                        catch (ex) {
                            isSupported = false;
                            handleError(initErrorMessage, ex);
                        }
                    }
                    function writeToDocument() {
                        try {
                            var windowTest = function (win) {
                                return bool(win.loaded);
                            };
                            writeHtml(getConsoleWindow().document);
                            if (windowTest(getConsoleWindow())) {
                                finalInit();
                            } else {
                                pollConsoleWindow(windowTest, finalInit, initErrorMessage);
                            }
                        }
                        catch (ex) {
                            isSupported = false;
                            handleError(initErrorMessage, ex);
                        }
                    }
                    minimized = initiallyMinimized;
                    iframeContainerDiv = containerElement.appendChild(document.createElement("div"));
                    iframeContainerDiv.style.width = width;
                    iframeContainerDiv.style.height = height;
                    iframeContainerDiv.style.border = "solid gray 1px";
                    var iframeHtml = "<iframe id='" + iframeId + "' name='" + iframeId + "' width='100%' height='100%' frameborder='0'" + "scrolling='no'></iframe>";
                    iframeContainerDiv.innerHTML = iframeHtml;
                    consoleClosed = false;
                    var iframeDocumentExistsTest = function (win) {
                        return bool(win) && bool(win.document);
                    };
                    if (iframeDocumentExistsTest(getConsoleWindow())) {
                        writeToDocument();
                    } else {
                        pollConsoleWindow(iframeDocumentExistsTest, writeToDocument, initErrorMessage);
                    }
                    initialized = true;
                };
                getConsoleWindow = function () {
                    var iframe = window.frames[iframeId];
                    if (iframe) {
                        return iframe;
                    }
                };
                safeToAppend = function () {
                    if (isSupported && !consoleClosed) {
                        if (!consoleWindowLoaded && getConsoleWindow() && getConsoleWindow().loaded) {
                            consoleWindowLoaded = true;
                        }
                        return consoleWindowLoaded;
                    }
                    return false;
                };
            } else {
                useOldPopUp = extractBooleanFromParam(useOldPopUp, appender.defaults.useOldPopUp);
                complainAboutPopUpBlocking = extractBooleanFromParam(complainAboutPopUpBlocking, appender.defaults.complainAboutPopUpBlocking);
                reopenWhenClosed = extractBooleanFromParam(reopenWhenClosed, this.defaults.reopenWhenClosed);
                this.isUseOldPopUp = function () {
                    return useOldPopUp;
                };
                this.setUseOldPopUp = function (useOldPopUpParam) {
                    if (checkCanConfigure("useOldPopUp")) {
                        useOldPopUp = bool(useOldPopUpParam);
                    }
                };
                this.isComplainAboutPopUpBlocking = function () {
                    return complainAboutPopUpBlocking;
                };
                this.setComplainAboutPopUpBlocking = function (complainAboutPopUpBlockingParam) {
                    if (checkCanConfigure("complainAboutPopUpBlocking")) {
                        complainAboutPopUpBlocking = bool(complainAboutPopUpBlockingParam);
                    }
                };
                this.isFocusPopUp = function () {
                    return focusConsoleWindow;
                };
                this.setFocusPopUp = function (focusPopUpParam) {
                    focusConsoleWindow = bool(focusPopUpParam);
                };
                this.isReopenWhenClosed = function () {
                    return reopenWhenClosed;
                };
                this.setReopenWhenClosed = function (reopenWhenClosedParam) {
                    reopenWhenClosed = bool(reopenWhenClosedParam);
                };
                this.close = function () {
                    try {
                        popUp.close();
                    }
                    catch (e) {
                    }
                    consoleClosed = true;
                };
                var popUp;
                init = function () {
                    var windowProperties = "width=" + width + ",height=" + height + ",status,resizable";
                    var windowName = "PopUp_" + location.host.replace(/[^a-z0-9]/gi, "_") + "_" + consoleAppenderId;
                    if (!useOldPopUp) {
                        windowName = windowName + "_" + uniqueId;
                    }
                    function finalInit() {
                        consoleWindowLoaded = true;
                        getConsoleWindow().setNewestAtTop(newestMessageAtTop);
                        getConsoleWindow().setScrollToLatest(scrollToLatestMessage);
                        getConsoleWindow().setMaxMessages(maxMessages);
                        appendQueuedLoggingEvents();
                    }
                    try {
                        popUp = window.open("", windowName, windowProperties);
                        consoleClosed = false;
                        if (popUp) {
                            if (useOldPopUp && popUp.loaded) {
                                popUp.mainPageReloaded();
                                finalInit();
                            } else {
                                writeHtml(popUp.document);
                                var popUpLoadedTest = function (win) {
                                    return bool(win) && win.loaded;
                                };
                                if (popUp.loaded) {
                                    finalInit();
                                } else {
                                    pollConsoleWindow(popUpLoadedTest, finalInit, "PopUpAppender.init: unable to create console window");
                                }
                            }
                        } else {
                            isSupported = false;
                            logLog.warn("PopUpAppender.init: pop-ups blocked, please unblock to use PopUpAppender");
                            if (complainAboutPopUpBlocking) {
                                handleError("log4javascript: pop-up windows appear to be blocked. Please unblock them to use pop-up logging.");
                            }
                        }
                    }
                    catch (ex) {
                        handleError("PopUpAppender.init: error creating pop-up", ex);
                    }
                    initialized = true;
                };
                getConsoleWindow = function () {
                    return popUp;
                };
                safeToAppend = function () {
                    if (isSupported && !isUndefined(popUp) && !consoleClosed) {
                        if (popUp.closed || (consoleWindowLoaded && isUndefined(popUp.closed))) {
                            consoleClosed = true;
                            logLog.debug("PopUpAppender: pop-up closed");
                            return false;
                        }
                        if (!consoleWindowLoaded && popUp.loaded) {
                            consoleWindowLoaded = true;
                        }
                    }
                    return isSupported && consoleWindowLoaded && !consoleClosed;
                };
            }
            if (enabled && !lazyInit) {
                init();
            }
            this.getConsoleWindow = getConsoleWindow;
        };
        var PopUpAppender = function (lazyInit, layout, focusPopUp, useOldPopUp, complainAboutPopUpBlocking, newestMessageAtTop, scrollToLatestMessage, reopenWhenClosed, width, height, maxMessages) {
            var focusConsoleWindow = extractBooleanFromParam(focusPopUp, this.defaults.focusPopUp);
            this.create(false, null, layout, lazyInit, focusConsoleWindow, useOldPopUp, complainAboutPopUpBlocking, newestMessageAtTop, scrollToLatestMessage, null, width, height, reopenWhenClosed, maxMessages);
        };
        PopUpAppender.prototype = new ConsoleAppender();
        PopUpAppender.prototype.defaults = {layout:new PatternLayout("%d{HH:mm:ss} %-5p - %m{1}%n"), focusPopUp:false, lazyInit:true, useOldPopUp:true, complainAboutPopUpBlocking:true, newestMessageAtTop:false, scrollToLatestMessage:true, width:"600", height:"400", reopenWhenClosed:false, maxMessages:null};
        PopUpAppender.prototype.toString = function () {
            return "[PopUpAppender]";
        };
        log4javascript.PopUpAppender = PopUpAppender;
        var InPageAppender = function (containerElement, lazyInit, layout, initiallyMinimized, newestMessageAtTop, scrollToLatestMessage, width, height, maxMessages) {
            this.create(true, containerElement, layout, lazyInit, false, null, null, newestMessageAtTop, scrollToLatestMessage, initiallyMinimized, width, height, null, maxMessages);
        };
        InPageAppender.prototype = new ConsoleAppender();
        InPageAppender.prototype.defaults = {layout:new PatternLayout("%d{HH:mm:ss} %-5p - %m{1}%n"), initiallyMinimized:false, lazyInit:true, newestMessageAtTop:false, scrollToLatestMessage:true, width:"100%", height:"250px", maxMessages:null};
        InPageAppender.prototype.toString = function () {
            return "[InPageAppender]";
        };
        log4javascript.InPageAppender = InPageAppender;
        log4javascript.InlineAppender = InPageAppender;
    })();
    var BrowserConsoleAppender = function (layout) {
        if (layout) {
            this.setLayout(layout);
        }
    };
    BrowserConsoleAppender.prototype = new log4javascript.Appender();
    BrowserConsoleAppender.prototype.layout = new NullLayout();
    BrowserConsoleAppender.prototype.threshold = Level.DEBUG;
    BrowserConsoleAppender.prototype.append = function (loggingEvent) {
        var appender = this;
        var getFormattedMessage = function () {
            var layout = appender.getLayout();
            var formattedMessage = layout.format(loggingEvent);
            if (layout.ignoresThrowable() && loggingEvent.exception) {
                formattedMessage += loggingEvent.getThrowableStrRep();
            }
            return formattedMessage;
        };
        if ((typeof opera != "undefined") && opera.postError) {
            opera.postError(getFormattedMessage());
        } else {
            if (window.console && window.console.log) {
                var formattedMesage = getFormattedMessage();
                if (window.console.debug && Level.DEBUG.isGreaterOrEqual(loggingEvent.level)) {
                    window.console.debug(formattedMesage);
                } else {
                    if (window.console.info && Level.INFO.equals(loggingEvent.level)) {
                        window.console.info(formattedMesage);
                    } else {
                        if (window.console.warn && Level.WARN.equals(loggingEvent.level)) {
                            window.console.warn(formattedMesage);
                        } else {
                            if (window.console.error && loggingEvent.level.isGreaterOrEqual(Level.ERROR)) {
                                window.console.error(formattedMesage);
                            } else {
                                window.console.log(formattedMesage);
                            }
                        }
                    }
                }
            }
        }
    };
    BrowserConsoleAppender.prototype.toString = function () {
        return "[BrowserConsoleAppender]";
    };
    log4javascript.BrowserConsoleAppender = BrowserConsoleAppender;
})();

